package cn.stylefeng.guns.modular.app.controller;

import cn.hutool.core.util.RandomUtil;
import cn.stylefeng.guns.core.shiro.ShiroKit;
import cn.stylefeng.guns.modular.app.entity.Member;
import cn.stylefeng.guns.modular.app.service.HomeService;
import cn.stylefeng.guns.modular.app.service.MemberService;
import cn.stylefeng.guns.modular.app.vo.LoginVo;
import cn.stylefeng.guns.modular.base.state.F;
import cn.stylefeng.guns.modular.base.state.ProConst;
import cn.stylefeng.guns.modular.base.util.Result;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.api.client.googleapis.auth.oauth2.*;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static cn.stylefeng.guns.modular.base.state.Constant.SYS_PLATFORM;

/**
 * <p>
 * 授权接口
 * </p>
 *
 * @author dudongjiang
 * @since 2023-02-03
 */
@CrossOrigin
@RequestMapping("/api/grant")
@RestController
public class GrantController {
//    private String CLIENT_ID = "328323026346-q344png1a5mhsmg2ffj3k0j0g02l9dt1.apps.googleusercontent.com";
    private String CLIENT_ID = "2739335434-b2g38l1r71a5hoqf0d4nisnbk7dap0oa.apps.googleusercontent.com";
//    private String CLIENT_SECRET = "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";
//     private String CLIENT_SECRET = "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";
    private String CLIENT_SECRET = "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";
    private String GRANT_URL = "https://oa.aesexchange.net";
    private String FRONT_GRANT_URL = "https://www.forexcoinmarket.com/login";
    private String FRONT_GRANT_H5_URL = "https://h5.forexcoinmarket.com/pages/login/login";
    private Logger logger = LoggerFactory.getLogger(GrantController.class);

    @Autowired
    private MemberService memberService;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HomeService homeService;

    @PostMapping("/googleLoginUri")
    public Result googleLoginUri()
    {
        try{
            GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
            GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
            details.setClientId(CLIENT_ID);
            details.setClientSecret(CLIENT_SECRET);
            clientSecrets.setInstalled(details);

            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

            List<String> scopes = Arrays.asList("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid");

            // 创建验证流程对象
            GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow
                    .Builder(httpTransport, jsonFactory, clientSecrets, scopes)
                    // AccessType为离线offline，才能获得Refresh Token
                    .setAccessType("offline").build();
            // 返回跳转登录请求
            String uri = googleAuthorizationCodeFlow.newAuthorizationUrl().setRedirectUri(FRONT_GRANT_URL).build();
            return Result.success(uri);
        } catch (GeneralSecurityException ex) {
            throw new RuntimeException(ex);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
    @PostMapping("/googleLoginUriH5")
    public Result googleLoginUriH5()
    {
        try{
            GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
            GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
            details.setClientId(CLIENT_ID);
            details.setClientSecret(CLIENT_SECRET);
            clientSecrets.setInstalled(details);

            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();

            List<String> scopes = Arrays.asList("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid");

            // 创建验证流程对象
            GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow
                    .Builder(httpTransport, jsonFactory, clientSecrets, scopes)
                    // AccessType为离线offline，才能获得Refresh Token
                    .setAccessType("offline").build();
            // 返回跳转登录请求
            String uri = googleAuthorizationCodeFlow.newAuthorizationUrl().setRedirectUri(FRONT_GRANT_H5_URL).build();
            return Result.success(uri);
        } catch (GeneralSecurityException ex) {
            throw new RuntimeException(ex);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
    @PostMapping("/googleCode")
    public Result googleCode(@RequestParam(required = false) String code)
    {
        try{
            GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
            GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
            details.setClientId(CLIENT_ID);
            details.setClientSecret(CLIENT_SECRET);
            clientSecrets.setInstalled(details);

            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
            // 创建验证流程对象
            List<String> scopes = Arrays.asList("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid");

            GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, clientSecrets, scopes)
                    // AccessType为离线offline，才能获得Refresh Token
                    .setAccessType("offline").build();

            GoogleAuthorizationCodeTokenRequest tokenRequest = googleAuthorizationCodeFlow.newTokenRequest(code);
            tokenRequest.setRedirectUri(FRONT_GRANT_URL);
            tokenRequest.setGrantType("authorization_code");
            GoogleTokenResponse tokenResponse = tokenRequest.execute();
            String token = tokenResponse.getAccessToken();

            logger.info("tokenResponse:{}",tokenResponse.toString());
            if (StringUtils.isNotBlank(tokenResponse.getIdToken())) {
                GoogleIdTokenVerifier idTokenVerifier = new GoogleIdTokenVerifier.Builder(googleAuthorizationCodeFlow.getTransport(), googleAuthorizationCodeFlow.getJsonFactory()).build();
                idTokenVerifier.verify(tokenResponse.getIdToken());
                GoogleIdToken googleIdToken = idTokenVerifier.verify(tokenResponse.getIdToken());
                if (googleIdToken != null && googleIdToken.getPayload() != null) {
                    googleIdToken.getPayload().getEmail();
                    //登录操作
                    GoogleIdToken.Payload payload = googleIdToken.getPayload();
                    return memberLogin(payload);
                }
            }
        }catch (Exception e){
            return Result.fail(300,e.getMessage());
        }
        return Result.fail(300);
    }
    @PostMapping("/googleCodeH5")
    public Result googleCodeH5(@RequestParam(required = false) String code)
    {
        try{
            GoogleClientSecrets clientSecrets = new GoogleClientSecrets();
            GoogleClientSecrets.Details details = new GoogleClientSecrets.Details();
            details.setClientId(CLIENT_ID);
            details.setClientSecret(CLIENT_SECRET);
            clientSecrets.setInstalled(details);

            HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
            // 创建验证流程对象
            List<String> scopes = Arrays.asList("https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid");

            GoogleAuthorizationCodeFlow googleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(httpTransport, jsonFactory, clientSecrets, scopes)
                    // AccessType为离线offline，才能获得Refresh Token
                    .setAccessType("offline").build();

            GoogleAuthorizationCodeTokenRequest tokenRequest = googleAuthorizationCodeFlow.newTokenRequest(code);
            tokenRequest.setRedirectUri(FRONT_GRANT_H5_URL);
            tokenRequest.setGrantType("authorization_code");
            GoogleTokenResponse tokenResponse = tokenRequest.execute();
            String token = tokenResponse.getAccessToken();

            logger.info("tokenResponse:{}",tokenResponse.toString());
            if (StringUtils.isNotBlank(tokenResponse.getIdToken())) {
                GoogleIdTokenVerifier idTokenVerifier = new GoogleIdTokenVerifier.Builder(googleAuthorizationCodeFlow.getTransport(), googleAuthorizationCodeFlow.getJsonFactory()).build();
                idTokenVerifier.verify(tokenResponse.getIdToken());
                GoogleIdToken googleIdToken = idTokenVerifier.verify(tokenResponse.getIdToken());
                if (googleIdToken != null && googleIdToken.getPayload() != null) {
                    googleIdToken.getPayload().getEmail();
                    //登录操作
                    GoogleIdToken.Payload payload = googleIdToken.getPayload();
                    return memberLogin(payload);
                }
            }
        }catch (Exception e){
            return Result.fail(300,e.getMessage());
        }
        return Result.fail(300);
    }

    /**
     * 会员登录
     * @param payload
     * @return
     */
    public Result memberLogin(GoogleIdToken.Payload payload){
        Member member = new Member();
        member.setAccount(payload.getEmail());

        //判断该用户账号是否存在
        if (memberService.getBaseMapper().getUserForOtherType(member.getAccount()) != null){
            //做登录
            LoginVo loginVo = new LoginVo();
            loginVo.setAccount(member.getAccount());
            loginVo.setPassword("123456");
            return homeService.login(loginVo);
        }
        // 完善账号信息
        String salt = ShiroKit.getRandomSalt(5);
        String password = ShiroKit.md5("123456", salt);

        String uid = RandomUtil.randomNumbers(6);
        while (true){
            Member uidM = new Member();
            uidM.setUid(uid);
            if (memberService.getOne(new QueryWrapper<>(uidM)) == null){
                break;
            }
            uid = RandomUtil.randomString(6);
        }
        String inviteCode = RandomUtil.randomStringUpper(8);
        while (true){
            Member uidM = new Member();
            uidM.setInviteCode(inviteCode);
            if (memberService.getOne(new QueryWrapper<>(uidM)) == null){
                break;
            }
            inviteCode = RandomUtil.randomStringUpper(8);
        }
        member.setAreaCode(ProConst.AccountType.EMAIL.code()).setEmail(member.getAccount());


        StringBuffer pids = new StringBuffer();
        pids.append("/");
        final String parentinviteCode = request.getHeader("icd");
        if (StringUtils.isNotBlank(parentinviteCode)){
            String registerInviteCode  = F.me().getSysConfigValueByCode("REGISTER_INVITE_CODE");
            if (StringUtils.isBlank(registerInviteCode) || !registerInviteCode.equals(inviteCode)){
                Member director  = F.me().getMember(null,inviteCode);
                if (director != null){
                    pids.append(director.getMemberId()).append(director.getParentRefereeId());
                    member.setRefereeId(director.getMemberId());
                }
            }
        }
        member.setPassword(password)
                .setSalt(salt).setValidStatus("N")
                .setParentRefereeId(pids.toString())
                .setType(ProConst.MemberType.V0.code())
                .setUid(uid)
                .setIsOpenPay("N")
                .setInviteCode(inviteCode)
                .setRegisterTime(new Date())
                .setCreateUser(SYS_PLATFORM);


        memberService.save(member);
        Member resultMemberQ_ = new Member();
        resultMemberQ_.setUid(uid);
        Member resultMember = memberService.getOne(new QueryWrapper<>(resultMemberQ_));

        //后台创建账号
        homeService.createUserAccount(resultMember,member.getPassword());

        /**
         * 是否有钱包，没有则创建一个钱包
         */
        homeService.generateWallet(resultMember);

        LoginVo loginVo = new LoginVo();
        loginVo.setAccount(member.getAccount());
        loginVo.setPassword("123456");
        return homeService.login(loginVo);
    }

    /**
     *
     * @param account
     * @return
     */
    @PostMapping("/googleGrantLogin")
    public Result googleGrantLogin(String account){
        Member member = new Member();
        member.setAccount(account);

        //判断该用户账号是否存在
        if (memberService.getBaseMapper().getUserForOtherType(member.getAccount()) != null){
            //做登录
            LoginVo loginVo = new LoginVo();
            loginVo.setAccount(member.getAccount());
            loginVo.setPassword("123456");
            return homeService.login(loginVo);
        }
        // 完善账号信息
        String salt = ShiroKit.getRandomSalt(5);
        String password = ShiroKit.md5("123456", salt);

        String uid = RandomUtil.randomNumbers(6);
        while (true){
            Member uidM = new Member();
            uidM.setUid(uid);
            if (memberService.getOne(new QueryWrapper<>(uidM)) == null){
                break;
            }
            uid = RandomUtil.randomString(6);
        }
        String inviteCode = RandomUtil.randomStringUpper(8);
        while (true){
            Member uidM = new Member();
            uidM.setInviteCode(inviteCode);
            if (memberService.getOne(new QueryWrapper<>(uidM)) == null){
                break;
            }
            inviteCode = RandomUtil.randomStringUpper(8);
        }
        member.setAreaCode(ProConst.AccountType.EMAIL.code()).setEmail(member.getAccount());


        StringBuffer pids = new StringBuffer();
        pids.append("/");

        member.setPassword(password)
                .setSalt(salt).setValidStatus("N")
                .setParentRefereeId(pids.toString())
                .setType(ProConst.MemberType.V0.code())
                .setUid(uid)
                .setIsOpenPay("N")
                .setInviteCode(inviteCode)
                .setRegisterTime(new Date())
                .setCreateUser(SYS_PLATFORM);


        memberService.save(member);
        Member resultMemberQ_ = new Member();
        resultMemberQ_.setUid(uid);
        Member resultMember = memberService.getOne(new QueryWrapper<>(resultMemberQ_));

        //后台创建账号
        homeService.createUserAccount(resultMember,member.getPassword());

        /**
         * 是否有钱包，没有则创建一个钱包
         */
        homeService.generateWallet(resultMember);

        LoginVo loginVo = new LoginVo();
        loginVo.setAccount(member.getAccount());
        loginVo.setPassword("123456");
        return homeService.login(loginVo);
    }
}
